#include "LoggerRegister.h"

namespace jmlib {

	LoggerRegister* LoggerRegister::getInstance() {
		static LoggerRegister* r = new LoggerRegister();
		return r;
	}

	void LoggerRegister::addAppender(const std::string& appenderName, 
		LogAppender* appender) {
			allAppendersByAppenderName_[appenderName] = appender;
			// Po pridani appendra este prelezem vsetky aktivacne filtre a 
			// tie co mu patri mu aj pridam.
			for (auto it = activationFilters_.begin(); 
				it != activationFilters_.end(); ++it) {
					if ((*it)->areAcceptedAllAppenders()) {
						appender->addActivationFilter(*it);
					} 
					else if ((*it)->getAppenderName() == appenderName) {
						appender->addActivationFilter(*it);
					}
			}
			// Pribudol novy appender a kde vsade ho pridat? -> Tak je potrebne 
			// radsej este pregenerovat priradenia vsetkych appendrov k logrom.
			rebuildAssignedAppendersByLoggerName();
	}

	void LoggerRegister::addLoggerActivator(const std::string& activatorfilter, 
		const std::string& appenderName, 
		LoggerActivatorFilter::FiltrationMethod filtrationMethod) {
			
			LoggerActivatorFilter* f = new LoggerActivatorFilter(
				activatorfilter, filtrationMethod, appenderName);
			activationFilters_.push_back(f);

			if (f->areAcceptedAllAppenders()) {
				for (auto it = allAppendersByAppenderName_.begin(); 
					it != allAppendersByAppenderName_.end(); ++it) {
						it->second->addActivationFilter(f);
				}
			}
			else {
				auto it = allAppendersByAppenderName_.find(f->getAppenderName());
				if (it != allAppendersByAppenderName_.end()) {
					it->second->addActivationFilter(f);
				}
			}
			// Rozne appendre dostali nove aktivacne kriteria -> mozu nalezat 
			// dalsim loggerom. Pregenerovania vsetkych priradeni to vyriesi.
			rebuildAssignedAppendersByLoggerName();
	}

	LoggerRegister::LogAppenderSet::iterator 
	LoggerRegister::getLogAppenderBegin(const std::string& loggerName) {
		return findAppendersByLoggerName(loggerName)->begin();
	}

	LoggerRegister::LogAppenderSet::iterator 
	LoggerRegister::getLogAppenderEnd(const std::string& loggerName) {
		return findAppendersByLoggerName(loggerName)->end();
	}

	void LoggerRegister::assignAppendersByLoggerName(
		const std::string& loggerName, LogAppenderSet* loggerAppenders) {
			for (auto it = allAppendersByAppenderName_.begin(); 
				it != allAppendersByAppenderName_.end(); ++it) {
					if (it->second->isLoggerAccepted(loggerName)) {
						loggerAppenders->insert(it->second);
					}
			}
	}

	void LoggerRegister::rebuildAssignedAppendersByLoggerName() {
		for (auto it = assignedAppendersByLogerName_.begin(); 
			it != assignedAppendersByLogerName_.end(); ++it) {
				// first == loggerName, second == pointer to logger 
				it->second->clear(); // zmazem predosle priradene appendre
				assignAppendersByLoggerName(it->first, it->second);
		}
	}

	LoggerRegister::LogAppenderSet* 
	LoggerRegister::findAppendersByLoggerName(const std::string& loggerName) {
		auto it = assignedAppendersByLogerName_.find(loggerName);
		if (it == assignedAppendersByLogerName_.end()) {
			static LogAppenderSet l;
			return &l;
		}
		else {
			return it->second;
		}
	}

} // namespace jmlib 
